/******************************************************************************

Welcome to GDB Online.
GDB online is an online compiler and debugger tool for C, C++, Python, Java, PHP, Ruby, Perl,
C#, OCaml, VB, Swift, Pascal, Fortran, Haskell, Objective-C, Assembly, HTML, CSS, JS, SQLite, Prolog.
Code, Compile, Run and Debug online from anywhere in world.

*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct _ringBuffer_t
{
    int *buffer;
    int read_offset;
    int write_offset;
    int valued_len;
    int total_len;
} ringBuffer_t;

#define LEN 100

int initRingBuffer(ringBuffer_t *ringBuffer)
{
    ringBuffer->buffer = (int *)malloc(LEN * sizeof(int));
    memset(ringBuffer->buffer, 0, LEN * sizeof(int));
    
    ringBuffer->read_offset = 0;
    ringBuffer->write_offset = 0;
    ringBuffer->valued_len = 0;
    ringBuffer->total_len = LEN;

    return 0;
}

int writeRingBuffer(ringBuffer_t *ringBuffer, int* input, int len)
{
    int freeSpace = ringBuffer->total_len - ringBuffer->valued_len;
    
    if (freeSpace < len) {
        return -1;
    }
    
    if (len <= (ringBuffer->total_len - ringBuffer->write_offset)) {
        memcpy((void *)&ringBuffer->buffer[ringBuffer->write_offset], input, len * sizeof(int));
    } else {
        int part1 = ringBuffer->total_len - ringBuffer->write_offset;
        int part2 = len - part1;
        
        memcpy((void *)&ringBuffer->buffer[ringBuffer->write_offset], input, part1 * sizeof(int));
        memcpy((void *)&ringBuffer->buffer[0], input + part1, part2 * sizeof(int));
    }
    
        ringBuffer->write_offset += len;
        ringBuffer->write_offset %= ringBuffer->total_len;

        ringBuffer->valued_len += len;
        
        return 0;
}

int readRingBuffer(ringBuffer_t *ringBuffer, int* output, int len)
{
    if (ringBuffer->valued_len < len) {
        return -1;
    }
    
    if (len <= (ringBuffer->total_len - ringBuffer->read_offset)) {
        memcpy(output, (void *)&ringBuffer->buffer[ringBuffer->read_offset], len * sizeof(int));
    } else {
        int part1 = ringBuffer->total_len - ringBuffer->read_offset;
        int part2 = len - part1;
        
        memcpy(output, (void *)&ringBuffer->buffer[ringBuffer->read_offset], part1 * sizeof(int));
        memcpy(output + part1, (void *)&ringBuffer->buffer[0],  part2 * sizeof(int));
    }
    
        ringBuffer->read_offset += len;
        ringBuffer->read_offset %= ringBuffer->total_len;

        ringBuffer->valued_len -= len;
        
        return 0;
}

int main()
{
    printf("Hello World\n");

    ringBuffer_t ringBuffer;
    initRingBuffer(&ringBuffer);
    
    int a[] = {1,4,6,2,8,1,6,9,11,88};
    writeRingBuffer(&ringBuffer, a, 10);
    
    int b[10] = {0};
    readRingBuffer(&ringBuffer, b, 10);
    
    for(int i = 0; i< 10; i++) {
        printf("%d ",b[i]);
    }
    
    return 0;
}
